﻿using System;
using System.Collections.Generic;
using System.Text;
using System.Web.UI.Design;
using Terralever.Facebook.UI.FbmlControls;
using System.Web.UI;
using System.ComponentModel;
using System.ComponentModel.Design;

namespace Terralever.Facebook.UI.Design.FbmlControls
{
    public class LogicTestControlDesigner : FbmlControlDesigner
    {
        #region region class
        private class LogicTestControlDesignerRegion : TemplatedEditableDesignerRegion
        {
            private object m_obj;
            private PropertyDescriptor m_pd;
            private ITemplate m_template;

            public LogicTestControlDesignerRegion(object obj, ITemplate template, PropertyDescriptor descriptor, TemplateDefinition definition)
                : base(definition)
            {
                m_obj = obj;
                m_template = template;
                m_pd = descriptor;
                base.EnsureSize = true;
            }

            public object Object { get { return m_obj; } }
            public ITemplate Template { get { return m_template; } set { m_template = value; } }
            public PropertyDescriptor PropertyDescriptor { get { return m_pd; } }
        }
        #endregion

        /// <inheritdoc />
        public override string GetEditableDesignerRegionContent(EditableDesignerRegion region)
        {
            LogicTestControlDesignerRegion rgn = region as LogicTestControlDesignerRegion;
            if (rgn != null)
            {
                ITemplate template = rgn.Template;
                if (template != null)
                {
                    IDesignerHost svc = (IDesignerHost)Component.Site.GetService(typeof(IDesignerHost));
                    return ControlPersister.PersistTemplate(template, svc);
                }
            }
            return base.GetEditableDesignerRegionContent(region);
        }

        /// <inheritdoc />
        public override void SetEditableDesignerRegionContent(EditableDesignerRegion region, string content)
        {
            LogicTestControlDesignerRegion rgn = region as LogicTestControlDesignerRegion;
            if (rgn != null)
            {
                IDesignerHost svc = (IDesignerHost)Component.Site.GetService(typeof(IDesignerHost));
                ITemplate template = ControlParser.ParseTemplate(svc, content);
                rgn.PropertyDescriptor.SetValue(rgn.Object, template);
                rgn.Template = template;
            }
        }

        /// <inheritdoc />
        public override void Initialize(System.ComponentModel.IComponent component)
        {
            base.Initialize(component);
        }

        /// <inheritdoc />
        public override string GetDesignTimeHtml(DesignerRegionCollection regions)
        {
            LogicTestControl ltc = Component as LogicTestControl;
            if (regions == null)
                return base.GetDesignTimeHtml(regions);

            if (ltc.DesignerDisplayMode == DesignerDisplayMode.Standard)
            {
                EditableDesignerRegion region = new LogicTestControlDesignerRegion(Component, ltc.IsValidTemplate, TypeDescriptor.GetProperties(Component)["IsValidTemplate"], IsValidTemplateDefinition);
                region.Description = "The template displayed to users who meet the requirements of viewing this control.";
                regions.Add(region);
                EditableDesignerRegion region2 = new LogicTestControlDesignerRegion(Component, ltc.IsNotValidTemplate, TypeDescriptor.GetProperties(Component)["IsNotValidTemplate"], NotValidTemplateDefinition);
                region2.Description = "The template displayed to users who do not meet the requirements of viewing this control.";
                regions.Add(region2);

                SetViewFlags(ViewFlags.TemplateEditing, true);

                return base.CreatePlaceHolderDesignTimeHtml("Click here and use the task menu to edit the conditional requirements templates.");
            }
            else if (ltc.DesignerDisplayMode == DesignerDisplayMode.LogicTestPassed)
            {
                EditableDesignerRegion region = new LogicTestControlDesignerRegion(Component, ltc.IsValidTemplate, TypeDescriptor.GetProperties(Component)["IsValidTemplate"], IsValidTemplateDefinition);
                region.Description = "The template displayed to users who meet the requirements of viewing this control.";
                regions.Add(region);

                SetViewFlags(ViewFlags.TemplateEditing, false);

                return "<div _designerRegion=\"0\" style=\"display: inline;\"></div>";
            }
            else
            {
                EditableDesignerRegion region2 = new LogicTestControlDesignerRegion(Component, ltc.IsNotValidTemplate, TypeDescriptor.GetProperties(Component)["IsNotValidTemplate"], NotValidTemplateDefinition);
                region2.Description = "The template displayed to users who do not meet the requirements of viewing this control.";
                regions.Add(region2);

                SetViewFlags(ViewFlags.TemplateEditing, false);

                return "<div _designerRegion=\"0\" style=\"display: inline;\"></div>";
            }
        }

        /// <inheritdoc />
        protected override bool UsePreviewControl
        {
            get
            {
                return true;
            }
        }

        private TemplateGroupCollection m_templateGroups;

        /// <inheritdoc />
        public override TemplateGroupCollection TemplateGroups
        {
            get
            {
                if (m_templateGroups == null)
                {
                    m_templateGroups = base.TemplateGroups;
                    TemplateGroup group = new TemplateGroup("All Templates");
                    group.AddTemplateDefinition(IsValidTemplateDefinition);
                    group.AddTemplateDefinition(NotValidTemplateDefinition);
                    m_templateGroups.Add(group);
                }

                return m_templateGroups;
            }
        }

        private TemplateDefinition m_tdIsValid, m_tdNotValid;
        private TemplateDefinition IsValidTemplateDefinition
        {
            get
            {
                if (m_tdIsValid == null)
                    m_tdIsValid = new TemplateDefinition(this, "Test Passed Template", Component, "IsValidTemplate", false);
                return m_tdIsValid;
            }
        }

        private TemplateDefinition NotValidTemplateDefinition
        {
            get
            {
                if (m_tdNotValid == null)
                    m_tdNotValid = new TemplateDefinition(this, "Test Failed Template", Component, "IsNotValidTemplate", false);
                return m_tdNotValid;
            }
        }

        public override bool AllowResize
        {
            get
            {
                return InTemplateMode;
            }
        }

        private class LogicTestControlDesignerActionList : DesignerActionList
        {
            private LogicTestControlDesigner m_designer;
            private DesignerActionUIService m_uiSvc;

            public LogicTestControlDesignerActionList(IComponent component, LogicTestControlDesigner designer)
                : base(component)
            {
                m_designer = designer;
                m_uiSvc = (DesignerActionUIService)GetService(typeof(DesignerActionUIService));
            }

            private PropertyDescriptor GetPropertyByName(string propName)
            {
                PropertyDescriptor prop = TypeDescriptor.GetProperties(Component)[propName];
                return prop;
            }

            private LogicTestControl Control
            {
                get { return Component as LogicTestControl; }
            }

            public override DesignerActionItemCollection GetSortedActionItems()
            {
                DesignerActionItemCollection list = new DesignerActionItemCollection();
                list.Add(new DesignerActionHeaderItem("Design Mode"));
                //list.Add(new DesignerActionPropertyItem("DesignerDisplayMode", "Display Mode"));

                //if (Control.DesignerDisplayMode != DesignerDisplayMode.Standard)
                //    list.Add(new DesignerActionMethodItem(this, "SetToStandardDisplay",
                //        "Display Standard View", "Design Mode", true));

                if (Control.DesignerDisplayMode != DesignerDisplayMode.LogicTestPassed)
                    list.Add(new DesignerActionMethodItem(this, "SetToValidDisplay",
                        "Display Logic Passed Template", "Design Mode", true));

                if (Control.DesignerDisplayMode != DesignerDisplayMode.LogicTestFailed)
                    list.Add(new DesignerActionMethodItem(this, "SetToInvalidDisplay",
                        "Display Logic Failed Template", "Design Mode", true));

                return list;
            }

            public void SetToStandardDisplay()
            {
                Control.DesignerDisplayMode = DesignerDisplayMode.Standard;
                m_designer.UpdateDisplay();
                m_uiSvc.Refresh(Component);
            }

            public void SetToValidDisplay()
            {
                Control.DesignerDisplayMode = DesignerDisplayMode.LogicTestPassed;
                m_designer.UpdateDisplay();
                m_uiSvc.Refresh(Component);
            }

            public void SetToInvalidDisplay()
            {
                Control.DesignerDisplayMode = DesignerDisplayMode.LogicTestFailed;
                m_designer.UpdateDisplay();
                m_uiSvc.Refresh(Component);
            }
        }

        private void UpdateDisplay()
        {
            base.UpdateDesignTimeHtml();
        }

        public override DesignerActionListCollection ActionLists
        {
            get
            {
                DesignerActionListCollection lists = base.ActionLists;
                lists.Add(new LogicTestControlDesignerActionList(this.Component, this));
                return lists;
            }
        }
    }
}
